﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Windows.Forms;
using CloudShot.Core.Interfaces;
using CloudShot.Core.Types;
using CloudShot.Core.Utils;
using CloudShot.Settings;
using DropboxImageStorage;

namespace CloudShot.Utils
{
	internal static class AppHelper
	{
		public static IEnumerable<Type> FindDerivedTypesFromAssembly(this Assembly assembly, Type baseType)
		{
			if (assembly == null)
				throw new ArgumentNullException("assembly", "Assembly must be defined");

			if (baseType == null)
				throw new ArgumentNullException("baseType", "Parent Type must be defined");

			Type[] types = assembly.GetExportedTypes();

			// works out the derived types
			foreach (var type in types)
			{
				// it must be a class
				if (!type.IsClass || type.IsAbstract)
					continue;

				if (baseType.IsInterface)
				{
					var it = type.GetInterface(baseType.FullName);

					if (it != null)
						// add it to result list
						yield return type;
				}
				else if (type.IsSubclassOf(baseType))
				{
					// add it to result list
					yield return type;
				}
			}
		}

		public static string GetFileName(ImageSaveFormat imageSaveFormat)
		{
			string date = string.Format("{0:yyMMdd_HHmmss}", DateTime.Now);
			return string.Format("shot_{0}.{1}", date, imageSaveFormat.GetImageExtension()).ToLower();
		}

		// <summary>
		// Get the name of a static or instance property from a property access lambda.
		// </summary>
		// <typeparam name="T">Type of the property</typeparam>
		// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
		// <returns>The name of the property</returns>
		public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
		{
			var me = propertyLambda.Body as MemberExpression;

			if (me == null)
			{
				throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
			}

			return me.Member.Name;
		}

		private static string _cloudShotAppData;
		public static string CloudShotAppData
		{
			get
			{
				if (string.IsNullOrEmpty(_cloudShotAppData))
					_cloudShotAppData = Application.UserAppDataPath.Replace(Application.ProductVersion, "");

				return _cloudShotAppData;
			}
		}

		private static string _defaultConfig;
		public static string DefaultConfig
		{
			get
			{
				if (string.IsNullOrEmpty(_defaultConfig))
					_defaultConfig = Path.Combine(Application.StartupPath, @"default.cfg");

				return _defaultConfig;
			}
		}

		private static string _configFile;
		public static string ConfigFile
		{
			get
			{
				if (string.IsNullOrEmpty(_configFile))
					_configFile = Path.Combine(CloudShotAppData, Application.ProductName + @".cfg");

				return _configFile;
			}
		}

		private static string _errorFile;
		public static string ErrorFile
		{
			get
			{
				if (string.IsNullOrEmpty(_errorFile))
					_errorFile = Path.Combine(CloudShotAppData, @"Error.log");

				return _errorFile;
			}
		}

		private static string _thumbnailsPath;
		public static string ThumbnailsPath
		{
			get
			{
				if (string.IsNullOrEmpty(_thumbnailsPath))
					_thumbnailsPath = Path.Combine(CloudShotAppData, @"Thumbnails");

				return _thumbnailsPath;
			}
		}

		private static string _pluginsPath;
		public static string PluginsPath
		{
			get
			{
				if (string.IsNullOrEmpty(_pluginsPath))
					_pluginsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"CloudShot\Plugins");

				return _pluginsPath;
			}
		}
	}
}